<?php
/**
 * Created by PhpStorm.
 * User: guokunsheng
 * Date: 2018/6/26
 * Time: 13:25
 */

namespace app\zyhsapi\controller\v1;

use app\common\cachemodel\UserAppleNotifyRecord;
use app\common\service\ApplePay;
use app\zyhsapi\lib\OrdersLib;
use app\zyhsapi\model\ZyhsUserAccountRecord;
use app\zyhsapi\model\ZyhsUserPush;
use app\zyhsmarketing\lib\RyMArk;
use app\zyhsmarketing\service\MarketingCallback;
use Exception;
use think\Controller;
use app\common\lib\PayCheckSign;
use think\db\exception\DataNotFoundException;
use think\db\exception\ModelNotFoundException;
use think\exception\DbException;
use think\Log;

/**
 * 支付回调相关接口
 * Class Notify
 * @package app\pay\controller
 */
class Notify extends Controller
{
    protected $config = [
        'APP' => 'wxpay',
        'JSAPI' => ['wxwebpay', 'wx_mini_astro_pay', 'wx_mini_astro_h5_pay'],
        'MWEB' => ['wxwebpay', 'wx_mini_astro_pay']
    ];

    public function apple()
    {
        $param = $this->request->param();
        Log::write('苹果回调数据:' . var_export($param, true) . PHP_EOL, 'apple_pay', true);
        return show(200, '', [], 200);
        $res = ApplePay::getInstance()->validateJwt($param['signedPayload']);
        if ($res)
        {
            $data = json_decode(json_encode($res['data'], true), true);
            $signedTransactionInfo = ApplePay::getInstance()->validateJwt($data['signedTransactionInfo']);//由 App Store 签名的交易信息
            $originalTransactionId = $signedTransactionInfo['originalTransactionId'];//原始交易ID
            $transactionId = $signedTransactionInfo['transactionId'];//当前交易ID
            $productId = $signedTransactionInfo['productId'];//当前产品ID
            $sub_type = $res['subtype'] ?? '';//标识通知事件的附加信息
            $res['signedTransactionInfoArr'] = $signedTransactionInfo;
//            Log::write('苹果回调数据解析:' . var_export($res, true) . PHP_EOL, 'log', true);

            $result = (new UserAppleNotifyRecord())->notifyInfo([
                'uuid' => $signedTransactionInfo['appAccountToken'] ?? '',
                'or_trans_id' => $originalTransactionId,
                'trans_id' => $transactionId,
                'product_id' => $productId,
                'notifi_type' => $res['notificationType'],
                'sub_type' => $sub_type,
                'notification_uuid' => $res['notificationUUID'],
                'purchase_date_ms' => $signedTransactionInfo['purchaseDate'],
            ]);
            if ($result)
            {
                return show(200, '', [], 200);
            }
            return show(0, '', [], 500);
        }
        return show(0, '', [], 500);
    }

    /**
     * 微信支付成功以后的回调
     *  <xml>
     *      <appid><![CDATA[wx2421b1c4370ec43b]]></appid>
     *      <attach><![CDATA[支付测试]]></attach>
     *      <bank_type><![CDATA[CFT]]></bank_type>
     *      <fee_type><![CDATA[CNY]]></fee_type>
     *      <is_subscribe><![CDATA[Y]]></is_subscribe>
     *      <mch_id><![CDATA[10000100]]></mch_id>
     *      <nonce_str><![CDATA[5d2b6c2a8db53831f7eda20af46e531c]]></nonce_str>
     *      <openid><![CDATA[oUpF8uMEb4qRXf22hE3X68TekukE]]></openid>
     *      <out_trade_no><![CDATA[1409811653]]></out_trade_no>
     *      <result_code><![CDATA[SUCCESS]]></result_code>
     *      <return_code><![CDATA[SUCCESS]]></return_code>
     *      <sign><![CDATA[B552ED6B279343CB493C5DD0D78AB241]]></sign>
     *      <sub_mch_id><![CDATA[10000100]]></sub_mch_id>
     *      <time_end><![CDATA[20140903131540]]></time_end>
     *      <total_fee>1</total_fee><coupon_fee><![CDATA[10]]></coupon_fee>
     *      <coupon_count><![CDATA[1]]></coupon_count>
     *      <coupon_type><![CDATA[CASH]]></coupon_type>
     *      <coupon_id><![CDATA[10000]]></coupon_id>
     *      <coupon_fee><![CDATA[100]]></coupon_fee>
     *      <trade_type><![CDATA[JSAPI]]></trade_type>
     *      <transaction_id><![CDATA[1004400740201409030005092168]]></transaction_id>
     *  </xml>
     * @return string xml
     * @throws Exception
     */
    public function wechat(): string
    {
        $returnStatus = ['return_code' => 'FAIL', 'return_msg' => '签名失败'];

        $xml = file_get_contents('php://input');

        \think\Log::write('微信支付回调参数' . var_export($xml, true), 'wx_pay', true);

        //检验xml格式
        $xml_parser = xml_parser_create();
        if (!xml_parse($xml_parser, $xml, true))
        {
            $data = [];
        } else
        {
            $data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        }
//         \think\Log::write('微信支付回调参数' . var_export($data, true), 'log', true);

        //验签名。默认支持MD5
        //获取订单支付账号配置
        $accountConfig = OrdersLib::getOrderAccountType($data['out_trade_no'], 2);
        $wxConfig = OrdersLib::getPayConfig('wx', $accountConfig['account']);

        if (!empty($data) && (new PayCheckSign)->weixin($data, $wxConfig['api_key']))
        {
            if ($data['return_code'] === 'SUCCESS'
                && $data['result_code'] === 'SUCCESS'
                && $data['appid'] === $wxConfig['appid']
                && $data['mch_id'] === $wxConfig['mchid'])
            {
                $out_trade_no = $data['out_trade_no'];// 订单号
                $total_fee = $data['total_fee'] / 100;// 订单总金额 单位为分

                // 回调逻辑处理
                $dbStatus = $this->notify_handle($out_trade_no, $total_fee, 2);
                if ($dbStatus)
                {
                    $returnStatus = [
                        'return_code' => 'SUCCESS',
                        'return_msg' => 'OK'
                    ];
                }
            }
        } else
        {
            Log::write(var_export($xml, true), 'log', true);
            Log::write(var_export($wxConfig, true), 'log', true);
            return false;
        }
        return $this->arrayToXml($returnStatus);
    }

    /**
     * 支付宝支付回调修改订单状态
     * notify_time 通知时间 Date 是 通知的发送时间。格式为yyyy-MM-dd HH:mm:ss 2015-14-27 15:45:58
     * notify_type 通知类型 String(64) 是 通知的类型 trade_status_sync
     * notify_id 通知校验ID String(128) 是 通知校验ID ac05099524730693a8b330c5ecf72da9786
     * app_id 支付宝分配给开发者的应用Id String(32) 是 支付宝分配给开发者的应用Id 2014072300007148
     * charset 编码格式 String(10) 是 编码格式，如utf-8、gbk、gb2312等 utf-8
     * version 接口版本 String(3) 是 调用的接口版本，固定为：1.0 1.0
     * sign_type 签名类型 String(10) 是 商户生成签名字符串所使用的签名算法类型，目前支持RSA2和RSA，推荐使用RSA2 RSA2
     * sign 签名 String(256) 是 请参考异步返回结果的验签 601510b7970e52cc63db0f44997cf70e
     * trade_no 支付宝交易号 String(64) 是 支付宝交易凭证号 2013112011001004330000121536
     * out_trade_no 商户订单号 String(64) 是 原支付请求的商户订单号 6823789339978248
     * trade_status 交易状态 String(32) 否 交易目前所处的状态，见交易状态说明 TRADE_CLOSED
     *      WAIT_BUYER_PAY 交易创建，等待买家付款 || TRADE_CLOSED  未付款交易超时关闭，或支付完成后全额退款 || TRADE_SUCCESS   交易支付成功 || TRADE_FINISHED     交易结束，不可退款
     * @throws Exception
     */
    public function ali(): void
    {
        $param = input('param.');

        \think\Log::write('支付宝支付回调参数:' . var_export($param, true), 'ali_pay', true);
        $returnStatus = 'fail';
        //获取订单账号类型
        $accountConfig = OrdersLib::getOrderAccountType($param['out_trade_no'], 1);
        $aliConfig = OrdersLib::getPayConfig('ali', $accountConfig['account']);
        // 签名成功
        if ((new PayCheckSign)->ali($_POST, $aliConfig))
        {
            $trade_status = $param['trade_status'] ?? '';

            if ($trade_status === 'TRADE_SUCCESS')
            {
                //===============如果支付成功，修改订单状态===========================//
                $out_trade_no = $param['out_trade_no'] ?? '';//获取订单号
                $app_id = $param['app_id'] ?? '';
                $seller_email = $param['seller_email'] ?? '';
                $seller_id = $param['seller_id'] ?? '';
                $total_amount = $param['total_amount'] ?? '';

                if (
                    $app_id === $aliConfig['app_id']
                    && $seller_email === $aliConfig['seller_email']
                    && $seller_id === $aliConfig['seller_id']
                )
                {
                    // 回调逻辑处理
                    $dbStatus = $this->notify_handle($out_trade_no, $total_amount, 1);
                    if ($dbStatus)
                    {
                        $returnStatus = 'success';
                    }
                }
            }
        }
        echo $returnStatus;
        exit;
    }

    /**
     * 回调后的逻辑处理
     * @param $order_id
     * @param $total_amount
     * @param $tradeType
     * @return bool
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     * @throws DbException
     */
    private function notify_handle($order_id, $total_amount, $tradeType): bool
    {
        $order = (new ZyhsUserAccountRecord())->where('order_id', $order_id)->field('uid,status')->find();
        if (!$order || $order['status'])
        {
            return true;
        }
        $tradeTypeDes = $tradeType === 1 ? 'alipay' : 'weixinpay';
        (new RyMArk())->recharge($tradeTypeDes, $order_id);//热云充值打点

        //安卓手机  充值回传打点
        $pushInfo = (new ZyhsUserPush())->getUserRegid($order['uid']);
        if ($pushInfo)
        {
            $oaid = $pushInfo['only_code'] ?? '';
            $mobileType = $pushInfo['push_type'] ?? 0;
            (new MarketingCallback())->uploadActiveData($oaid, (int)$order['uid'], 3, $mobileType);
        }
        return OrdersLib::UpdateCoin($order_id, 10, $total_amount, $order['uid'], 1, $tradeType);
    }

    /**
     * 数组转xml
     * @param $arr
     * @return string
     */
    private function arrayToXml($arr): string
    {
        $xml = '<xml>';
        foreach ($arr as $key => $val)
        {
            if (is_numeric($val))
            {
                $xml .= '<' . $key . '>' . $val . '</' . $key . '>';

            } else
            {
                $xml .= '<' . $key . '><![CDATA[' . $val . ']]></' . $key . '>';
            }
        }
        $xml .= '</xml>';
        return $xml;
    }
}
